package main;

import java.util.HashMap;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;


/**
 * ContentHandler zum Umwandeln einer ODT Datei in das SimpleText XML Format.
 */
class ODTContentHandler extends DefaultHandler {
    /**
     * Dient zur Zwischenspeicherung der SimpleText XML Formates.
     */
    private String buffer;

    /**
     * Speichert den Namen des zuletzt gefundenen Stilnamens.
     */
    private String currentListStyleName;

    /**
     * Gibt an, ob beim Aufruf der Characters Funktion die gefunden Textstellen mit in den Buffer geschrieben werden sollen.
     */
    private Boolean writeCharacters;

    /**
     * Gibt an, ob der aktuelle Arbeitsschritt innerhalb eines note-Tags stattfindet.
     */
    private Boolean inNote;

    /**
     * Gibt an, ob der aktuelle Arbeitsschritt innerhalb eines list-Tags stattfindet.
     */
    private Boolean inList;

    /**
     * Map zur Zuordnung von Aufzaehlungs-Typen. Der Key beinhaltet den Namen des Stiles und der Integer
     * repraesentiert eine nummerierte (1)  oder eine nicht nummerierte (0) Liste.
     */
    private HashMap<String,Integer> listStyles;

    /**
     * Speichert die Tiefe der aktuellen Einrueckung.
     */
    private int depth;


    /**
     * Initialisiert den Handler mit Standardwerten und schreibt die Headerdaten in den SimpleText Buffer.
     */
    public ODTContentHandler() {
        this.buffer = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + System.getProperty("line.separator") +
                      "<!DOCTYPE Text SYSTEM \"SimpleText.dtd\">" + System.getProperty("line.separator");
        this.currentListStyleName = new String();
        this.depth = 0;
        this.writeCharacters = false;
        this.inNote = false;
        this.inList = false;
        this.listStyles = new HashMap<String,Integer>();
    }

    /**
     * Methode zur Verarbeitung von Start-Tags.
     *
     * @see DefaultHandler
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        
        if(localName.equals("body")) {
            add("<Text>");
            this.depth++;
            this.writeCharacters = true;
        }
        
        if(localName.equals("h")) {
            add("<Ueberschrift>");
            this.depth++;
            this.writeCharacters = true;
        }
        
        if(localName.equals("p")) {
            this.writeCharacters = true;
            
            if(this.inNote) {
                //do nothing
            } else if (this.inList) {
                add("<Item>");
                this.depth++;
            } else {
                add("<Absatz>");
                this.depth++;
            }
            
        }
              
        if(localName.equals("note")) {
            this.inNote = true;
        }
        
        if(localName.equals("list")) {
            if(!this.inList) {
                this.add("<Aufzaehlung nummeriert=\"" + this.listStyles.get(atts.getValue("text:style-name")) + "\">");
                this.depth++;
                this.inList = true;
            }
        }
        
        if(localName.equals("list-style")) {
            this.currentListStyleName = atts.getValue("style:name");
        }

        if(localName.equals("list-level-style-number")) {
            this.listStyles.put(this.currentListStyleName, 1);
        }
        
        if(localName.equals("list-level-style-bullet")) {
            this.listStyles.put(this.currentListStyleName, 0);
        }
        
    }

    /**
     * Methode zur Verarbeitung von End-Tags.
     *
     * @see DefaultHandler
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        
        if(localName.equals("body")) {
            this.depth--;
            add("</Text>");
        }
        
        if(localName.equals("h")) {
            this.depth--;
            add("</Ueberschrift>");
        }
        
        if(localName.equals("p")) {
            if(this.inNote) {
               //do nothing
            } else if(this.inList) {
                this.depth--;
                add("</Item>");
            } else {
                this.depth--;
                add("</Absatz>");
            }
        }
        
        if(localName.equals("note")) {
            this.inNote = false;
        }
        
        if(localName.equals("list")) {
            if(this.inList) {
                this.inList = false;
                this.depth--;
                this.add("</Aufzaehlung>");
            }
        }

    }

    /**
     * Methode zur Verarbeitung von Textstellen.
     *
     * @see DefaultHandler
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if(this.writeCharacters){
            if(this.inNote) {
                this.add("(" + new String(ch, start, length) + ")");
            } else {            
                this.add(new String(ch, start, length));
            }
        }
        
        this.writeCharacters = false;
    }

    /**
     * Liefert den SimpleText Buffer
     *
     * @return den Buffer
     */
    public String getBuffer() {
        return this.buffer;
    }

    /**
     * Fuegt dem SimpleText Buffer eine neue Zeile mit entsprechender Einrueckung hinzu.
     * @param text
     */
    private void add(String text) {
        String indent = "";
        
        if(this.depth > 0) {
           indent = String.format(String.format("%%0%dd", this.depth), 0).replace("0","\t");
        }
        this.buffer = this.buffer.concat(indent + text + System.getProperty("line.separator"));
    }
}
